package com.cazor.dg.app;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.cazor.common.core.domain.AjaxResult;
import com.cazor.common.utils.StringUtils;
import com.cazor.dg.common.DgSysCacheService;
import com.cazor.dg.domain.DgConfigContentType;
import com.cazor.dg.domain.DgDeviceSensor;
import com.cazor.dg.domain.DgParamDataSensor;
import com.cazor.dg.domain.DgRequestHis;
import com.cazor.dg.domain.vo.AppDataReSendVo;
import com.cazor.dg.service.*;
import com.cazor.mg.domain.MgParamLog;
import com.cazor.mg.service.IMgParamLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class AppDataReSendService {
    @Resource
    private AppService appService;
    @Resource
    private AppReqService appReqService;
    @Resource
    private IDgMonitorStationService monitorStationService;
    @Resource
    private IDgDevDeviceInstanceService devDeviceInstanceService;
    @Resource
    private IDgDeviceSensorService deviceSensorService;
    @Resource
    private IAdgLoginTokenHisService loginTokenHisService;
    @Resource
    private DgSysCacheService dgSysCacheService;
    @Resource
    private IMgParamLogService mgParamLogService;
    @Resource
    private IDgConfigContentTypeService configContentTypeService;
    @Resource
    private IDgParamDataSensorService paramDataSensorService;


    public AjaxResult getToken() {
        try {
            String token = appReqService.getToken();
            return AjaxResult.success(token);
        }catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error(e.getMessage());
        }
    }

    public AjaxResult reSendWithOutHisData(AppDataReSendVo queryVo) {
        DateTime beginTime = queryVo.getBeginTime(), endTime = queryVo.getEndTime();
        if (beginTime == null || endTime == null) {
            return AjaxResult.warn("时间范围不能为空");
        }
        // 不需要传的传感器 ids
        List<String> sensorIdsNotIn = queryVo.getSensorIdsNotIn();
        List<String> sensorIds = queryVo.getSensorIds();

        LambdaQueryChainWrapper<DgParamDataSensor> paramDataQuery = paramDataSensorService.lambdaQuery();
        if (CollectionUtil.isNotEmpty(sensorIds)) {
            paramDataQuery.in(DgParamDataSensor::getSensorId, sensorIds);
        }
        if (CollectionUtil.isNotEmpty(sensorIdsNotIn)) {
            paramDataQuery.notIn(DgParamDataSensor::getSensorId, sensorIdsNotIn);
        }

        List<DgParamDataSensor> paramDataSensorList = paramDataQuery.list();
        int count = CollectionUtil.size(paramDataSensorList);
        if(count > 0) {
            int i =1;
            for (DgParamDataSensor paramDataSensor : paramDataSensorList) {
                this.insertDevDeviceParamData(paramDataSensor, beginTime, endTime);
                log.info("[ReSendWithOutHisData] 完成：{} -- {}/{}"
                        , paramDataSensor.getSensorId(), i++, count);
            }
        }

        log.info("[ReSendWithOutHisData] 全部完成...");
        return AjaxResult.success();
    }


    public void insertDevDeviceParamData(DgParamDataSensor paramDataSensor, DateTime beginTime, DateTime endTime) {
        String sensorId = paramDataSensor.getSensorId();
        Date maxReadDate = paramDataSensor.getUpdateTime();
        if (StringUtils.isBlank(sensorId) || maxReadDate == null) {
            log.warn("[ReSendWithOutHisData]  sensorId({}) / maxReadDate({}) 为空 不能查询"
                    , sensorId
                    , maxReadDate==null?"null":DateTime.of(maxReadDate).toString(DatePattern.NORM_DATETIME_PATTERN));
            return;
        }
        DgDeviceSensor sensor = dgSysCacheService.getDeviceSensor(paramDataSensor.getSensorId());
        DgConfigContentType configContentType = dgSysCacheService.getConfigContentType(sensor.getContentType());
        if (sensor == null || configContentType == null) {
            log.warn("[ReSendWithOutHisData]  传感器({})-获取到 DgDeviceSensor / DgConfigContentType 为 null", sensorId);
            return;
        }
        // 获取时间范围内 该传感器 数据
        List<MgParamLog> paramLogList = this.getMgParamLog(sensorId, beginTime, endTime);

        int count = CollectionUtil.size(paramLogList);
        log.info("[ReSendWithOutHisData] 传感器:{} 待上传的数据总量:{}", sensorId, count);

        if (count > 0) {
            DateTime readDateDt = null;
            // 排序
            paramLogList = paramLogList.stream()
                    .sorted(Comparator.comparing(MgParamLog::getReadDate)).collect(Collectors.toList());
            // 对于同一个传感器 多条监测数据 每6条数据分一组
            List<List<MgParamLog>> paramLogSplitList = ListUtil.split(paramLogList, 6);
//            log.info("paramLogSplitList.count:{}", CollectionUtil.size(paramLogSplitList));
            JSONObject requestParams = null, reqJson = null;
            DgRequestHis requestHis = null;
            List<Long> requestHisIdList = new ArrayList<>(CollectionUtil.size(paramLogSplitList));
            for (List<MgParamLog> logList : paramLogSplitList) {
//                log.info("开始执行数据封装: logList.size--{}", CollectionUtil.size(logList));
                requestParams = appService.initDeviceInstancesData(logList, paramDataSensor, sensor, configContentType);
//                System.out.println(requestParams);
                reqJson = appReqService.insertDevDeviceParamData(requestParams);
                if (reqJson!=null && reqJson.getInteger("code") == 200) {
                    requestHis = reqJson.getObject("requestHis", DgRequestHis.class);
                    if (requestHis!=null) {
                        requestHisIdList.add(requestHis.getId());
                    }
                } else {
                    log.error("传感器({})--提交接口异常:{}"
                            , sensorId, reqJson!=null?reqJson.getString("message"):"null");
                }
            }
            MgParamLog lastParamLog = paramLogList.get(count-1);
            readDateDt = DateTime.of(lastParamLog.getReadDate());
            if (maxReadDate.compareTo(readDateDt)<0) {
                DgParamDataSensor updateObj = new DgParamDataSensor();
                updateObj.setId(paramDataSensor.getId());
                updateObj.setMaxId(lastParamLog.getId());
                updateObj.setUpdateTime(lastParamLog.getReadDate());
                paramDataSensorService.updateById(updateObj);
            }
            log.info("传感器({})--提交数据完成:hisIdList:{}", sensorId, requestHisIdList);
        }else {
            log.warn("传感器({})--获取监测数据为空！", sensorId);
        }



    }


    /**
     * 获取 某个传感器(sensorId) 大于某时间(maxReadDate) 的所有记录数据
     * @param sensorId 传感器id
     * @param beginTime 开始时间
     * @param endTime 截止时间
     * @return 列表
     */
    public List<MgParamLog> getMgParamLog(String sensorId, DateTime beginTime, DateTime endTime) {
//        log.info("sensorId={}, maxReadDate={}, maxReadDateStr={}"
//                ,  sensorId, maxReadDate, DateTime.of(maxReadDate).toString(DatePattern.NORM_DATETIME_PATTERN));
        MgParamLog queryParams = new MgParamLog();
        queryParams.setParentCode(sensorId);
        Map<String, Object> params = new HashMap<>();
        params.put("beginReadDate", beginTime);
        params.put("endReadDate", endTime);
        queryParams.setParams(params);

        return mgParamLogService.selectMgParamLogList(queryParams);
    }
}
